<?php

namespace App\Http\Services\Api\V1\App\Customer;

use App\Http\Controllers\Api\V1\App\Customers\ThirdPartyLoginController;
use App\Models\Customers\QqUser;
use App\Models\Setting;
use App\Services\Utils\ApiChecker;
use Laravel\Socialite\Facades\Socialite;
use \SocialiteProviders\Manager\OAuth2\User;

class QqService
{
    use ApiChecker;

    const OAUTH_TYPE_QQ_APP = 'qq_app';
    const OAUTH_TYPE_QQ_PC = 'qq_pc';
    const KEY_OAUTH_QQ_APP_APP_ID = 'oauth_qq_app_app_id';
    const KEY_OAUTH_QQ_PC_APP_ID = 'oauth_qq_pc_app_id';
    const KEY_OAUTH_QQ_APP_APP_SECRET = 'oauth_qq_app_app_secret';
    const KEY_OAUTH_QQ_PC_APP_SECRET = 'oauth_qq_pc_app_secret';
    const PC_REDIRECT_URL = '%s/index.php?route=account/login/oauthCallback&type=%s';

    /**
     * @return \SocialiteProviders\Manager\Config
     */
    public function setQqConfig()
    {
        $clientId = Setting::getSettingSpecifyValue(self::KEY_OAUTH_QQ_PC_APP_ID);
        $clientSecret = Setting::getSettingSpecifyValue(self::KEY_OAUTH_QQ_PC_APP_SECRET);
        $redirectUrl = route('pc_oauth_callback', self::OAUTH_TYPE_QQ_PC);
        $config = new \SocialiteProviders\Manager\Config($clientId, $clientSecret, $redirectUrl);

        return $config;
    }

    /**
     * @return \SocialiteProviders\Manager\Config
     */
    public function setAppQqConfig()
    {
        $clientId = Setting::getSettingSpecifyValue(self::KEY_OAUTH_QQ_APP_APP_ID);
        $clientSecret = Setting::getSettingSpecifyValue(self::KEY_OAUTH_QQ_APP_APP_SECRET);
        $redirectUrl = '';
        $config = new \SocialiteProviders\Manager\Config($clientId, $clientSecret, $redirectUrl);

        return $config;
    }

    /**
     * app端处理QQ第三方登录，获取QQ用户的信息
     * @return mixed
     * @throws \Exception
     */
    public function handleQqCallback()
    {
        // 设置配置文件
        $config = $this->setAppQqConfig();

        // laravel/socialite 请求的认证 ,可以用stateless（）禁止会话状态验证。
        session(['state' => 890]);
        request()->offsetSet('state', 890);

        $user = $this->createOrUpdateUser($config, self::OAUTH_TYPE_QQ_APP);

        return $user;
    }

    /**
     * pc端处理QQ第三方登录，获取配置信息
     * @return mixed
     */
    public function generateQqProvider()
    {
        $config = $this->setQqConfig();

        return Socialite::driver('qq')->setConfig($config);
    }

    /**
     * pc端处理QQ第三方登录，获取QQ用户的信息
     * @return \App\Models\Customers\Customer|array|\Illuminate\Database\Eloquent\Model|null|object
     * @throws \Exception
     */
    public function qqCallback()
    {
        $config = $this->setQqConfig();

        $user = $this->createOrUpdateUser($config, self::OAUTH_TYPE_QQ_PC);

        $data = http_build_query([
            'customer_id'   => $user->customer_id ?? '',
            'token'         => $user->jwt_token ?? '',
            'type'          => self::OAUTH_TYPE_QQ_PC,
            'oauth_user_id' => $user['oauth_user_id'] ?? '',
        ]);

        return redirect(sprintf(self::PC_REDIRECT_URL, config('app.web-url'), self::OAUTH_TYPE_QQ_PC.'&'.$data));
    }

    /**
     * @param $config
     * @param $type
     * @return \App\Models\Customers\Customer|array|\Illuminate\Database\Eloquent\Model|null|object|User
     * @throws \Exception
     */
    public function createOrUpdateUser($config, $type)
    {
        try {
            /** @var User $user */
            $user =  Socialite::driver('qq')->setConfig($config)->user();
        } catch (\Exception $e){
            logger($e->getMessage());
            $this->checkIsTrue(false, trans('customer.qq_oauth_error'));
        }

        $qq_data = $this->assembleQqUser($user);
        $qq_user = $this->updateOrCreateUser($qq_data);

        $user = (new ThirdPartyService)->generateUser($qq_user, $type);

        return $user;
    }

    /**
     * @param User $user
     * @return array
     */
    public function assembleQqUser(User $user)
    {
        $qq_user_data = [
            'id'       => $user->id ?? '',
            'unionid'  => $user->unionId ?? '',
            'nickname' => $user->nickname ?? '',
            'name'     => $user->name ?? '',
            'email'    => $user->email ?? '',
            'avatar'   => $user->avatar ?? '',
        ];

        return $qq_user_data;

    }

    /**
     * @param array $qq_user_data
     * @return QqUser
     */
    public function updateOrCreateUser(array $qq_user_data)
    {
        /** @var QqUser $qq_user */
        $qq_user = (new QqUser)->updateOrCreate (
            ['id' => $qq_user_data['id']], $qq_user_data
        );

        return $qq_user;
    }
}